﻿using System;
using Tiny.Imaging.Filter.PixelLibrary;

namespace Tiny.Imaging.Filter.PointFilter
{
    public class SaturationFilter : BaseFilter.BaseFilter
    {
        private readonly RgbChannel _channel;
        private readonly float _factor;

        private float[] _mapping;

        public SaturationFilter(float factor = 0, RgbChannel channel = RgbChannel.Rgb, Func<int, int, int> blend = null, int opacity = 100)
            : base(blend, opacity)
        {
            _factor = factor * -0.01f;
            _channel = channel;
            PrePopulate();
        }

        private void PrePopulate()
        {
            _mapping = new float[256];
            for (int i = 0; i < 256; ++i)
            {
                _mapping[i] = i * _factor;
            }
        }

        public override int Process(Rgba rgba)
        {
            Rgba result = new Rgba { R = rgba.R, G = rgba.G, B = rgba.B };
            int max = Math.Max(Math.Max(rgba.R, rgba.G), rgba.B);
            int diff = 0;

            if ((_channel & RgbChannel.R) == RgbChannel.R &&
                rgba.R != max)
            {
                diff = max - rgba.R;
                result.R = MathLibrary.MathLibrary.Clamp(rgba.R + _mapping[diff]);
            }

            if ((_channel & RgbChannel.G) == RgbChannel.G &&
                rgba.G != max)
            {
                diff = max - rgba.G;
                result.G = MathLibrary.MathLibrary.Clamp(rgba.G + _mapping[diff]);
            }

            if ((_channel & RgbChannel.B) == RgbChannel.B &&
                rgba.B != max)
            {
                diff = max - rgba.B;
                result.B = MathLibrary.MathLibrary.Clamp(rgba.B + _mapping[diff]);
            }

            return BlendRgba(rgba, result).ToInteger();
        }
    }
}